package de.distMLP;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hama.HamaConfiguration;

import de.distMLP.train.Configuration;

public class Helper {
	private Helper() {
		super();
	}

	static void printOutput(final HamaConfiguration conf, final Path path, final boolean deleteOutput) throws IOException {
		final FileSystem fs = FileSystem.get(conf);
		final FileStatus[] files = fs.listStatus(path);
		for (final FileStatus file : files) {
			if (file.getLen() > 0) {
				final FSDataInputStream in = fs.open(file.getPath());
				IOUtils.copyBytes(in, System.out, conf, false);
				in.close();
				break;
			}
		}
		if (deleteOutput) {
			fs.delete(path, true);
		}
	}

	public static HamaConfiguration getConfig(final String[] args) throws IOException {
		if (args.length != 1) {
			System.out.println("Usage: jar <path to properties file>");
			System.exit(1);
		}
		final HamaConfiguration conf = new HamaConfiguration();

		final Properties prop = new Properties();
		prop.load(new FileInputStream(args[0]));

		conf.setInt(Configuration.NB_INPUT_UNITS, Integer.parseInt(prop.getProperty(Configuration.NB_INPUT_UNITS)));
		conf.setInt(Configuration.NB_OUTPUT_UNITS, Integer.parseInt(prop.getProperty(Configuration.NB_OUTPUT_UNITS)));
		conf.setBoolean(Configuration.MUTUALLY_EXCLUSIVE_CLASSES, Boolean.parseBoolean(prop.getProperty(Configuration.NB_OUTPUT_UNITS)));
		conf.set(Configuration.TRAININGS_DATA_INPUT_PATH, prop.getProperty(Configuration.TRAININGS_DATA_INPUT_PATH));
		conf.setInt(Configuration.NB_ITERATIONS, Integer.parseInt(prop.getProperty(Configuration.NB_ITERATIONS)));

		conf.setBoolean(Configuration.LOAD_MLP, Boolean.parseBoolean(prop.getProperty(Configuration.LOAD_MLP)));
		conf.setBoolean(Configuration.SAVE_MLP, Boolean.parseBoolean(prop.getProperty(Configuration.SAVE_MLP)));
		conf.set(Configuration.MLP_INPUT_PATH, prop.getProperty(Configuration.MLP_INPUT_PATH));
		conf.set(Configuration.MLP_OUTPUT_PATH, prop.getProperty(Configuration.MLP_OUTPUT_PATH));
		conf.setBoolean(Configuration.SGD, Boolean.parseBoolean(prop.getProperty(Configuration.SGD, "false")));

		conf.setBoolean(Configuration.MINI_BATCH_GD, Boolean.parseBoolean(prop.getProperty(Configuration.MINI_BATCH_GD, "false")));

		conf.setBoolean(Configuration.SPARSE_AUTOENCODER, Boolean.parseBoolean(prop.getProperty(Configuration.SPARSE_AUTOENCODER, "false")));

		conf.setBoolean(Configuration.R_PROP, Boolean.parseBoolean(prop.getProperty(Configuration.R_PROP, "false")));

		conf.setInt(Configuration.NUMBER_OF_BSP_TASKS, Integer.parseInt(prop.getProperty(Configuration.NUMBER_OF_BSP_TASKS, "0")));

		conf.setInt(Configuration.BATCH_SIZE, Integer.parseInt(prop.getProperty(Configuration.BATCH_SIZE, "0")));

		conf.set(Configuration.REGULARIZATION, prop.getProperty(Configuration.REGULARIZATION, "0.01"));

		conf.set(Configuration.LEARNINGRATE, prop.getProperty(Configuration.LEARNINGRATE, "0.1"));

		conf.setBoolean(Configuration.USE_ADAGRAD, Boolean.parseBoolean(prop.getProperty(Configuration.USE_ADAGRAD, "false")));

		conf.set(Configuration.ADAGRAD_ETA, prop.getProperty(Configuration.ADAGRAD_ETA, "0.01"));

		conf.setBoolean(Configuration.USE_CACHE, Boolean.parseBoolean(prop.getProperty(Configuration.USE_CACHE, "false")));
		conf.setBoolean(Configuration.USE_TEST_SEED, Boolean.parseBoolean(prop.getProperty(Configuration.USE_TEST_SEED, "false")));

		conf.setInt(Configuration.SAVE_INTERVAL, Integer.parseInt(prop.getProperty(Configuration.SAVE_INTERVAL, "10")));

		conf.setBoolean(Configuration.NG_WIDROW_RANDOMIZER,
				Boolean.parseBoolean(prop.getProperty(Configuration.NG_WIDROW_RANDOMIZER, "false")));
		conf.setBoolean(Configuration.LOROT_BENGIO_RANDOMIZER,
				Boolean.parseBoolean(prop.getProperty(Configuration.LOROT_BENGIO_RANDOMIZER, "false")));

		conf.setBoolean(Configuration.USE_BINARY_TREE_COLLECTIVE_COMMUNICATION,
				Boolean.parseBoolean(prop.getProperty(Configuration.USE_BINARY_TREE_COLLECTIVE_COMMUNICATION, "false")));

		if (prop.containsKey(Configuration.MOMENTUM)) {
			conf.set(Configuration.MOMENTUM, prop.getProperty(Configuration.MOMENTUM));
		}

		final int nbHiddenLayer = Integer.parseInt(prop.getProperty(Configuration.NB_HIDDEN_LAYERS));
		conf.setInt(Configuration.NB_HIDDEN_LAYERS, nbHiddenLayer);
		for (int i = 0; i < nbHiddenLayer; i++) {
			conf.setInt(Configuration.NB_UNITS_HIDDEN_LAYER + (i + 1),
					Integer.parseInt(prop.getProperty(Configuration.NB_UNITS_HIDDEN_LAYER + (i + 1))));
		}

		conf.setBoolean(Configuration.DENOISE_INPUT, Boolean.parseBoolean(prop.getProperty(Configuration.DENOISE_INPUT, "false")));

		conf.setBoolean(Configuration.SPLIT_INPUT, Boolean.parseBoolean(prop.getProperty(Configuration.SPLIT_INPUT, "false")));

		conf.setBoolean(Configuration.CALCULATE_ERROR_ON_EACH_ITERATION,
				Boolean.parseBoolean(prop.getProperty(Configuration.CALCULATE_ERROR_ON_EACH_ITERATION, "true")));

		conf.setInt(Configuration.SEED_VALUE, Integer.parseInt(prop.getProperty(Configuration.SEED_VALUE, "-1")));

		conf.setInt(Configuration.REPEAT_WHOLE_TRAINING, Integer.parseInt(prop.getProperty(Configuration.REPEAT_WHOLE_TRAINING, "0")));

		conf.setFloat(Configuration.TARGET_ERROR, Float.parseFloat(prop.getProperty(Configuration.TARGET_ERROR, "-1")));

		conf.setBoolean(Configuration.MOCKUP_TEST, Boolean.parseBoolean(prop.getProperty(Configuration.MOCKUP_TEST, "false")));

		return conf;
	}
}
